package cc.owoo.godpen.file;

import cc.owoo.godpen.util.Path;

import java.util.HashMap;

/**
 * 文件路径节点
 * Created by nimensei
 * 2022-04-07 下午 12:56
 **/
public class PathMap {
    private final HashMap<String, PathMap> child = new HashMap<>();// 子路径

    public PathMap() {
    }

    public PathMap(Path path) {
        if (path == null || path.size() == 0)
            return;
        child.put(path.removeFirstName(), new PathMap(path));
    }

    /**
     * 判断传入的路径是否存在，或存在他的父路径
     *
     * @param path 路径
     * @return 是否存在，或存在他的父路径
     */
    public boolean containsParent(Path path) {
        if (path.size() == 0)
            return false;
        return recursionParentGet(path.copy()) != null;
    }

    /**
     * 获取节点，或父节点
     *
     * @param path 路径
     * @return 路径自身节点，或父节点
     */
    public PathMap getParent(Path path) {
        if (path.size() == 0)
            return this;
        return recursionParentGet(path.copy());
    }

    /**
     * 添加路径，并判断是否存在父路径，如果存在则添加失败
     *
     * @param path 需要添加的路径
     * @return 是否添加成功
     */
    public boolean addIfParent(Path path) {
        if (path.size() == 0)
            return false;
        return recursionAddIfParent(path.copy());
    }

    /**
     * 判断传入的路径是否存在
     *
     * @param path 路径
     * @return 是否存在
     */
    public boolean contains(Path path) {
        if (path.size() == 0)
            return false;
        return recursionGet(path.copy()) != null;
    }

    /**
     * 获取路径所在的节点
     *
     * @param path 路径
     * @return 节点
     */
    public PathMap get(Path path) {
        if (path.size() == 0)
            return this;
        return recursionGet(path.copy());
    }

    /**
     * 添加路径，如果路径已存在，则返回false，否则返回true
     *
     * @param path 需要添加的路径
     * @return 是否添加成功
     */
    public boolean add(Path path) {
        if (path.size() == 0)
            return false;
        AddResult res = recursionAdd(path.copy());
        return res.isNew;
    }

    /**
     * 添加路径，并返回路径所在节点
     *
     * @param path 需要添加的路径
     * @return 路径所在节点
     */
    public PathMap addAndGet(Path path) {
        if (path.size() == 0)
            return this;
        AddResult res = recursionAdd(path.copy());
        return res.map;
    }

    /**
     * 查找路径，如果路径存在，或存在路径的父路径，则返回这个节点
     *
     * @param path 需要查找的路径
     * @return 节点
     */
    private PathMap recursionGet(Path path) {
        String name = path.removeFirstName();
        PathMap map = child.get(name);
        if (map == null)
            return null;
        return path.size() == 0 ? map : map.recursionGet(path);
    }

    /**
     * 获取父节点或本身节点
     *
     * @param path 需要查找的路径
     * @return 节点
     */
    private PathMap recursionParentGet(Path path) {
        String name = path.removeFirstName();
        PathMap map = child.get(name);
        if (map == null)
            return null;
        PathMap child = map.recursionGet(path);
        return child == null ? map : child;
    }

    /**
     * 添加路径，如果路径已存在，则返回false，否则返回true
     *
     * @param path 需要添加的路径
     * @return 是否添加成功
     */
    private AddResult recursionAdd(Path path) {
        String name = path.removeFirstName();
        PathMap map = child.get(name);
        if (map == null) {
            child.put(name, map = new PathMap(path));
            return new AddResult(true, map);
        }
        if (path.size() == 0)
            return new AddResult(false, map);
        return map.recursionAdd(path);
    }

    /**
     * 添加路径，并判断是否存在父路径，如果存在则添加失败
     *
     * @param path 需要添加的路径
     * @return 是否添加成功
     */
    private boolean recursionAddIfParent(Path path) {
        String name = path.removeFirstName();
        PathMap map = child.get(name);
        if (map == null) {
            child.put(name, new PathMap(path));
            return true;
        }
        if (path.size() == 0)
            return false;
        if (map.child.size() == 0)
            return false;
        return map.recursionAddIfParent(path);
    }

    /**
     * 添加的结果
     */
    private record AddResult(boolean isNew, PathMap map) {
    }
}
